/*
 *  $Id: Point.cs 1209 2010-11-23 16:57:24Z thenn.erannor $
 *	This file is a part of Ragima CCG.
 *	(C) 2008-2010 Ragima development group.
 *
 *	Licensed under the terms of the GNU GPL License version 2.
 *
 */

using System;

using AgateLib.Geometry;

namespace Ragima.Helper {
    /// <summary>
    /// Расширения для структур Point и PointF.
    /// </summary>
    public static class PointExtensions {
        /// <summary>
        /// Сравнивает две точки на приблизительное равенство.
        /// </summary>
        public static bool ApproxEquals(this PointF p1, PointF p2) {
            return Math.Abs(p2.X - p1.X) < 1 && Math.Abs(p2.Y - p1.Y) < 1;
        }

        /// <summary>
        /// Складывает координаты двух точек.
        /// </summary>
        public static Point Add(this Point p1, Point p2) {
            return new Point(p1.X + p2.X, p1.Y + p2.Y);
        }
        /// <summary>
        /// Складывает координаты двух точек.
        /// </summary>
        public static PointF Add(this PointF p1, PointF p2) {
            return new PointF(p1.X + p2.X, p1.Y + p2.Y);
        }

        /// <summary>
        /// Вычитает координаты одной точки из другой.
        /// </summary>
        public static Point Sub(this Point p1, Point p2) {
            return new Point(p1.X - p2.X, p1.Y - p2.Y);
        }
        /// <summary>
        /// Вычитает координаты одной точки из другой.
        /// </summary>
        public static PointF Sub(this PointF p1, PointF p2) {
            return new PointF(p1.X - p2.X, p1.Y - p2.Y);
        }

        /// <summary>
        /// Получает точку путем отступа от исходной точки.
        /// </summary>
        public static Point Padding(this Point point, int padding) {
            if (padding == 0)
                return point;
            return new Point(point.X + padding, point.Y + padding);
        }

        /// <summary>
        /// Вычисляет расстояние от нуля до указанных координат.
        /// </summary>
        private static double GetDistance(double x, double y) {
            return Math.Sqrt(x * x + y * y);
        }

        /// <summary>
        /// Вычисляет расстояние от нуля до точки.
        /// </summary>
        public static double GetDistance(this Point point) {
            return GetDistance(point.X, point.Y);
        }
        /// <summary>
        /// Вычисляет расстояние от нуля до точки.
        /// </summary>
        public static double GetDistance(this PointF point) {
            return GetDistance(point.X, point.Y);
        }

        /// <summary>
        /// Вычисляет расстояние между двумя точками.
        /// </summary>
        public static double GetDistance(this Point p1, Point p2) {
            return GetDistance(p2.X - p1.X, p2.Y - p1.Y);
        }
        /// <summary>
        /// Вычисляет расстояние между двумя точками.
        /// </summary>
        public static double GetDistance(this PointF p1, PointF p2) {
            return GetDistance(p2.X - p1.X, p2.Y - p1.Y);
        }

        /// <summary>
        /// Вычисляет угол от нуля к указанным координатам.
        /// </summary>
        private static double GetAngle(double x, double y) {
            return Math.Atan2(y, x).ToDegrees().NormalizeAngle();
        }

        /// <summary>
        /// Вычисляет угол от нуля к точке.
        /// </summary>
        public static double GetAngle(this Point point) {
            return GetAngle(point.X, point.Y);
        }
        /// <summary>
        /// Вычисляет угол от нуля к точке.
        /// </summary>
        public static double GetAngle(this PointF point) {
            return GetAngle(point.X, point.Y);
        }

        /// <summary>
        /// Вычисляет угол от одной точки к другой.
        /// </summary>
        public static double GetAngle(this Point p1, Point p2) {
            return GetAngle(p2.X - p1.X, p2.Y - p1.Y);
        }
        /// <summary>
        /// Вычисляет угол от одной точки к другой.
        /// </summary>
        public static double GetAngle(this PointF p1, PointF p2) {
            return GetAngle(p2.X - p1.X, p2.Y - p1.Y);
        }

        /// <summary>
        /// Переводит указанные координаты в полярные.
        /// </summary>
        private static PolarPoint ToPolar(double x, double y) {
            return new PolarPoint(GetAngle(x, y), GetDistance(x, y));
        }

        /// <summary>
        /// Переводит точку в полярную.
        /// </summary>
        public static PolarPoint ToPolar(this Point point) {
            return ToPolar(point.X, point.Y);
        }
        /// <summary>
        /// Переводит точку в полярную.
        /// </summary>
        public static PolarPoint ToPolar(this PointF point) {
            return ToPolar(point.X, point.Y);
        }

        /// <summary>
        /// Переводит точку в полярную относительно указанного центра.
        /// </summary>
        public static PolarPoint ToPolar(this Point point, Point center) {
            return ToPolar(point.X - center.X, point.Y - center.Y);
        }
        /// <summary>
        /// Переводит точку в полярную относительно указанного центра.
        /// </summary>
        public static PolarPoint ToPolar(this PointF point, PointF center) {
            return ToPolar(point.X - center.X, point.Y - center.Y);
        }

        /// <summary>
        /// Конвертирует точку из целочисленных координат в дробные.
        /// </summary>
        public static PointF ToF(this Point point) {
            return new PointF(point.X, point.Y);
        }
    }
}
